package com.health.view.spinner;

import java.util.List;

import com.health.R;
import com.health.tablebean.BD_DD_INFO;

import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

/**
 * @author angelo.marchesin
 */
@SuppressLint("NewApi")
@SuppressWarnings("unused")
public class NiceSpinner extends TextView {

	private static final int MAX_LEVEL = 10000;
	private static final int DEFAULT_ELEVATION = 16;
	private static final String INSTANCE_STATE = "instance_state";
	private static final String SELECTED_INDEX = "selected_index";
	private static final String IS_POPUP_SHOWING = "is_popup_showing";

	private int mSelectedIndex;
	private Drawable mDrawable;
	private PopupWindow mPopup;
	private ListView mListView;
	private NiceSpinnerBaseAdapter mAdapter;
	private AdapterView.OnItemClickListener mOnItemClickListener;
	private AdapterView.OnItemSelectedListener mOnItemSelectedListener;
	private boolean mHideArrow;

	@SuppressWarnings("ConstantConditions")
	public NiceSpinner(Context context) {
		super(context);
		init(context, null);
	}

	public NiceSpinner(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context, attrs);
	}

	public NiceSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context, attrs);
	}

	@Override
	public Parcelable onSaveInstanceState() {
		Bundle bundle = new Bundle();
		bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
		bundle.putInt(SELECTED_INDEX, mSelectedIndex);

		if (mPopup != null) {
			bundle.putBoolean(IS_POPUP_SHOWING, mPopup.isShowing());
			dismissDropDown();
		}

		return bundle;
	}

	@Override
	public void onRestoreInstanceState(Parcelable savedState) {
		if (savedState instanceof Bundle) {
			Bundle bundle = (Bundle) savedState;

			mSelectedIndex = bundle.getInt(SELECTED_INDEX);

			if (mAdapter != null) {
				if (mAdapter.getItemInDataset(mSelectedIndex) instanceof BD_DD_INFO) {
					BD_DD_INFO item = (BD_DD_INFO) mAdapter.getItemInDataset(mSelectedIndex);
					setText(item.getDATAINFO());
				} else {
					setText(mAdapter.getItemInDataset(mSelectedIndex).toString());
				}
				mAdapter.notifyItemSelected(mSelectedIndex);
			}

			if (bundle.getBoolean(IS_POPUP_SHOWING)) {
				if (mPopup != null) {
					// Post the show request into the looper to avoid bad token
					// exception
					post(new Runnable() {
						@Override
						public void run() {
							showDropDown();
						}
					});
				}
			}

			savedState = bundle.getParcelable(INSTANCE_STATE);
		}

		super.onRestoreInstanceState(savedState);
	}

	@SuppressLint("NewApi")
	private void init(Context context, AttributeSet attrs) {
		Resources resources = getResources();
		TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NiceSpinner);
		int defaultPadding = resources.getDimensionPixelSize(R.dimen.one_and_a_half_grid_unit);

		setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
		setPadding(resources.getDimensionPixelSize(R.dimen.three_grid_unit), defaultPadding, defaultPadding,
				defaultPadding);
		setClickable(true);
		setBackgroundResource(R.drawable.selector);

		mListView = new ListView(context);
		// Set the spinner's id into the listview to make it pretend to be the
		// right parent in
		// onItemClick
		mListView.setId(getId());
		mListView.setDivider(null);
		mListView.setItemsCanFocus(true);
		mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				if (position >= mSelectedIndex && position < mAdapter.getCount()) {
					position++;
				}

				// Need to set selected index before calling listeners or
				// getSelectedIndex() can be
				// reported incorrectly due to race conditions.
				mSelectedIndex = position;

				if (mOnItemClickListener != null) {
					mOnItemClickListener.onItemClick(parent, view, position, id);
				}

				if (mOnItemSelectedListener != null) {
					mOnItemSelectedListener.onItemSelected(parent, view, position, id);
				}

				mAdapter.notifyItemSelected(position);
				if (mAdapter.getItemInDataset(position) instanceof BD_DD_INFO) {
					BD_DD_INFO item = (BD_DD_INFO) mAdapter.getItemInDataset(position);
					setText(item.getDATAINFO());
				} else {
					setText(mAdapter.getItemInDataset(position).toString());
				}
				dismissDropDown();
			}
		});

		mPopup = new PopupWindow(context);
		mPopup.setContentView(mListView);
		mPopup.setOutsideTouchable(true);
		mPopup.setFocusable(true);

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
			mPopup.setElevation(DEFAULT_ELEVATION);
			mPopup.setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.spinner_drawable));
		} else {
			mPopup.setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.drop_down_shadow));
		}

		mPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
			@Override
			public void onDismiss() {
				if (!mHideArrow) {
					animateArrow(false);
				}
			}
		});

		mHideArrow = typedArray.getBoolean(R.styleable.NiceSpinner_hideArrow, false);
		if (!mHideArrow) {
			Drawable basicDrawable = ContextCompat.getDrawable(context, R.drawable.spinner_arrow);
			int resId = typedArray.getColor(R.styleable.NiceSpinner_arrowTint, -1);

			if (basicDrawable != null) {
				mDrawable = DrawableCompat.wrap(basicDrawable);

				if (resId != -1) {
					DrawableCompat.setTint(mDrawable, resId);
				}
			}
			setCompoundDrawablesWithIntrinsicBounds(null, null, mDrawable, null);
		}

		typedArray.recycle();
	}

	public int getSelectedIndex() {
		return mSelectedIndex;
	}

	/**
	 * Set the default spinner item using its index
	 * 
	 * @param position
	 *            the item's position
	 */
	public void setSelectedIndex(int position) {
		if (mAdapter != null) {
			if (position >= 0 && position <= mAdapter.getCount()) {
				mAdapter.notifyItemSelected(position);
				mSelectedIndex = position;
				if (mAdapter.getItemInDataset(position) instanceof BD_DD_INFO) {
					BD_DD_INFO item = (BD_DD_INFO) mAdapter.getItemInDataset(position);
					setText(item.getDATAINFO());
				} else {
					setText(mAdapter.getItemInDataset(position).toString());
				}
			} else {
				throw new IllegalArgumentException("Position must be lower than adapter count!");
			}
		}
	}

	public void addOnItemClickListener(@NonNull AdapterView.OnItemClickListener onItemClickListener) {
		mOnItemClickListener = onItemClickListener;
	}

	public void setOnItemSelectedListener(@NonNull AdapterView.OnItemSelectedListener onItemSelectedListener) {
		mOnItemSelectedListener = onItemSelectedListener;
	}

	public <T> void attachDataSource(@NonNull List<T> dataset) {
		mAdapter = new NiceSpinnerAdapter<>(getContext(), dataset);
		setAdapterInternal(mAdapter);
	}

	public void setAdapter(@NonNull ListAdapter adapter) {
		mAdapter = new NiceSpinnerAdapterWrapper(getContext(), adapter);
		setAdapterInternal(mAdapter);
	}

	private void setAdapterInternal(@NonNull NiceSpinnerBaseAdapter adapter) {
		mListView.setAdapter(adapter);
		// setText(((BD_DD_AREA)adapter.getItemInDataset(mSelectedIndex)).getNAME().toString());
		if (mAdapter.getItemInDataset(mSelectedIndex) instanceof BD_DD_INFO) {
			BD_DD_INFO item = (BD_DD_INFO) mAdapter.getItemInDataset(mSelectedIndex);
			setText(item.getDATAINFO());
		} else {
			Object ob = adapter.getItemInDataset(mSelectedIndex);
			if (null != ob) {
				setText(ob.toString());
			}
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		mPopup.setWidth(View.MeasureSpec.getSize(widthMeasureSpec));
		mPopup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	public boolean onTouchEvent(@NonNull MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_UP) {
			if (!mPopup.isShowing()) {
				showDropDown();
			} else {
				dismissDropDown();
			}
		}

		return super.onTouchEvent(event);
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	@SuppressLint("NewApi")
	private void animateArrow(boolean shouldRotateUp) {
		int start = shouldRotateUp ? 0 : MAX_LEVEL;
		int end = shouldRotateUp ? MAX_LEVEL : 0;
		ObjectAnimator animator = ObjectAnimator.ofInt(mDrawable, "level", start, end);
		animator.setInterpolator(new LinearOutSlowInInterpolator());
		animator.start();
	}

	public void dismissDropDown() {
		if (!mHideArrow) {
			animateArrow(false);
		}
		mPopup.dismiss();
	}
	
	  /**
	   *动态获取listview的高度
	 * @param adapter
	 * @param listView
	 * @return
	 */
	private int getListheight(Adapter adapter, ListView listView) {  
          
	        //对适配器的数据进行判空操作  
	        if(adapter == null) {  
	            return 0;  
	        }           
	        //设置ListView的底部高度  
	        int totalHeight = 0;  
	        //遍历适配器数据，获取到每一个item的高度并进行统计  
	        for (int i = 0; i < adapter.getCount(); i++) {  
	            View listItem = adapter.getView(i, null, listView);    //获取到ListView中item对应的view  
	            listItem.measure(0, 0);                                //获取到view的高度  
	            totalHeight += listItem.getMeasuredHeight();        //获取到所有item的总高度  
	        }     
	        //获取到总高度：item总高度+线条总高度（线条比item数少一个）  
	        totalHeight = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1));  
	        return totalHeight;  
	    }    

	public void showDropDown() {
		if (!mHideArrow) {
			animateArrow(true);
		}

		int[] location = new int[2];
		this.getLocationOnScreen(location);

		Log.e("dddddddddeeeeeee", "" + location[0] + "\n" + location[1]);
		Log.e("dddddddddeeeeeee", "getListheight(mAdapter, mListView)" + getListheight(mAdapter, mListView));
		if (location[1] > 730) {

			mPopup.showAtLocation(this, Gravity.NO_GRAVITY, location[0], location[1] - getListheight(mAdapter, mListView));
		} else {
			mPopup.showAsDropDown(this);
		}

	}

	public void setTintColor(@ColorRes int resId) {
		if (mDrawable != null && !mHideArrow) {
			DrawableCompat.setTint(mDrawable, getResources().getColor(resId));
		}
	}
}
